/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "ara_controller.h"
#include "loghelper.h"
#include "access_rule_driver.h"
#include "secure_element_agent.h"

namespace OHOS {
namespace SE {
using namespace std;
std::shared_ptr<AccessRuleDriver> g_accessRuleDriver = nullptr;
std::vector<uint8_t> g_SaveAccessRuleData;
/*
 * Software that is part of the Secure Element access API, it obtains access
 * rules from the Secure Element and applies those rules to restrict device
 * application access to the various Secure Element applications.
 */
AraController::AraController(std::weak_ptr<SecureElementAgent> agent)
{
    agent_ = agent;
}

AraController::~AraController()
{
}

bool AraController::IsNeedRefresh()
{
    // The ARA-M is an ordinary SE application which can be selected by a GlobalPlatform-defined AID.
    std::string araMAid = "A00000015141434C00";
    std::string response;
    // todo : get access rule from aid list which is stored in xml
    // get access rule from ISD-M
    if (agent_.expired()) {
        ErrorLog("agent_ is null.");
        return false;
    }

    channel_ = agent_.lock()->OpenLogicalChannelWithoutChannelAccess(araMAid, 0, response);
    if (channel_ == nullptr) {
        ErrorLog("fail to get logicalchannel.");
        return false;
    }

    if (g_accessRuleDriver == nullptr) {
        InfoLog("First need new");
        g_accessRuleDriver = std::make_shared<AccessRuleDriver>(channel_);
    } else {
        InfoLog("Not first, update used channel");
        g_accessRuleDriver->UpdateChannel(channel_);
    }

    std::vector<uint8_t> retRefreshTag;
    if (g_accessRuleDriver->ReadRefreshTag(retRefreshTag) != BER_RET_SUCCESS) {
        ErrorLog("fail to get refreshTag.");
    }
    if ((g_accessRuleDriver->GetRefreshTag() == retRefreshTag) && !g_SaveAccessRuleData.empty()) {
        ErrorCode ret = channel_->Close();
        InfoLog("No Need refresh, channel close ret = %{public}d.", ret);
        return false;
    }

    g_accessRuleDriver->SaveRefreshTag(retRefreshTag);
    return true;
}

ErrorCode AraController::ReadAllAccessRules(std::vector<uint8_t> &retAccessRuleData)
{
    InfoLog("Need refresh");
    if (g_accessRuleDriver == nullptr || channel_ == nullptr) {
        return ErrorCode::SE_NULL_POINTER_ERROR;
    }

    if (g_accessRuleDriver->ReadAllAccessRules(retAccessRuleData) != 0) {
        ErrorCode ret = channel_->Close();
        ErrorLog("fail to read all accessRules, ret = %{public}d.", ret);
        retAccessRuleData.assign(g_SaveAccessRuleData.begin(), g_SaveAccessRuleData.end());
        return ErrorCode::SE_ACCESS_CONTROL_ERROR;
    }
    g_SaveAccessRuleData.assign(retAccessRuleData.begin(), retAccessRuleData.end());
    ErrorCode ret = channel_->Close();
    return ret;
}

}  // namespace SE
}  // namespace OHOS

